from urllib.parse import urljoin
from common.send_requests import *
from Model.user import *
from Model.environment import Environment
from Model.user import PcUser, AppUser
import uuid
import random


def timeStamp():
    time.sleep(0.01)
    return int(time.time()*1000)


class TransportOrder:
    # 状态
    status = None
    # 大门
    door = None
    # 地磅
    weighbridge_name = None
    # 卡号
    card_no = None
    # 榜单
    pound_order_no = None
    # 装货数据
    loadings = None
    # 车牌号
    plate_number = None
    # 车辆重量
    car_weight = 3
    # 冻结单号
    freeze_no = None
    # 物流单号
    logistics_order_no = None
    # 退回详情
    return_details = None

    def __init__(self, puser, auser, transport_no, store_dict, env):
        self.puser: PcUser = puser
        self.auser: AppUser = auser
        self.transport_no = transport_no
        self.store_dict = store_dict
        self.env: Environment = env

    def transport_order_quest(self):
        self.get_transport_order_detail()
        self.plate_number = self.info["plateNumber"]
        self.status = self.info["transportStatusTypeName"]
        self.card_no = self.info["cardNo"]
        if len(self.info["loadings"]):
            self.loadings = self.info["loadings"]
            warehouseName = self.info["loadings"][0]["warehouseName"]
            store = self.store_dict[warehouseName]
            self.door = store["entry"]
            weighbridge_name = store["weighbridgeNames"]
            if len(weighbridge_name) < 1:
                self.weighbridge_name = ""
            else:
                self.weighbridge_name = weighbridge_name[0]
        self.get_transport_order_pound_info()
        if len(self.pound_info) > 0:
            self.pound_order_no = self.pound_info[0]["poundOrderNo"]
            self.pound_weight = self.pound_info[0]["weight"]
        else:
            self.pound_order_no = f"BD{int(time.time())}"

    def get_transport_order_pound_info(self):
        # 获取过磅信息
        url = urljoin(self.env.realmName, "loading-order/measure-records")
        params = {
            "transportOrderNo": self.transport_no
        }
        res = sendRequest(url, "get", headers=self.puser.headers,
                          params=params, msg="获取过磅信息")
        self.pound_info = res.json()

    def get_transport_order_detail(self):
        # 运输单详情
        url = urljoin(self.env.realmName, "transport-order/detail")
        params = {
            "orderNo": self.transport_no,
            "IncludeLoading": True
        }
        res = sendRequest(url, "get", headers=self.puser.headers,
                          params=params, msg="运输单详情")
        self.info = res.json()
        self.queueStatusName = self.info["queueStatusName"]
        self.logistics_order_no = self.info["logisticsOrderNo"]
        self.sourceNo = self.info["sourceNo"]
        # self.currentStoreName = self.info["currentStoreName"]

    def transport_order_allot(self):
        # 配货
        url = urljoin(self.env.realmName, "transport-order-task/allot")
        data = {
            "no": self.transport_no
        }
        res = sendRequest(url, "post", data,
                          headers=self.puser.headers, msg="配货接口")

        if res.status_code == 200:
            if res.json()["queueStatusName"] == "未配货":
                self.status = res.json()["extraProperties"]["CargoAllotResult"]
            else:
                self.status = "已配货"

    def transport_order_challenge(self, transport_no):
        # 叫号
        transports_info = self.get_transport_order_detail()
        if transports_info["queueStatusName"] != "允许进厂":
            print("未叫号，开始叫号")
            self.transport_order_enter_auth()
        self.status = "允许进厂"

    def transport_order_enter_auth(self):
        # 运输单入厂授权
        url = urljoin(self.env.realmName, "transport-order-task/enter-auth")
        data = {
            "no": self.transport_no
        }
        res = sendRequest(url, "post", data,
                          headers=self.puser.headers, msg="运输单入厂授权")
        return res.json()

    def transport_order_into_factory(self):
        # 查询进厂大门
        url = urljoin(
            self.env.realmName, "acs-system/finish-product-in-out-vehicle-log")
        data = {
            "pastChannel": "进口通道",
            "pastChannelName": "进口通道",
            "inOrOut": "进",
            "inOrOutDatetime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            "past": self.door,
            "pastName": self.door,
            "envPicUrl": "https://dummyimage.com/180x150",
            "plateColor": "Y",
            "carPicUrl": "https://dummyimage.com/180x150",
            "inOrOutID": str(uuid.uuid1()),
            "calculateNo": self.transport_no
        }
        res = sendRequest(url, "post", data, self.puser.headers, "入厂")
        if res.status_code == 200:
            self.status = res.json()["message"]
        else:
            self.status = f"入厂失败: {res.text}"

    def transport_order_first_loadmeter(self):
        # 首次过磅
        url = urljoin(self.env.realmName, "les-system/weight")
        data = {
            # 固定
            "cardType": 14,
            # 当前过磅次数
            "alreadyWeightCount": 1,
            # 重量
            "weight": self.car_weight*1000,
            # ==============地磅名称=证仓库库别-关联地磅
            "weighbridgeName": self.weighbridge_name,
            "weightType": 1,
            "callbacksure": 0,
            "callCode": 0,
            # 卡号
            "cardNo": self.card_no,
            # 装车单号
            "cardOrderNo": self.transport_no,
            # 磅单号
            "poundOrderNo": self.pound_order_no,
            "operator": "张三模拟"
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.puser.headers, msg="首次过磅")
        if str(res.json()["codeState"]) != "1":
            print(f"二次过磅失败")
            exit()
        self.status = "已过磅未装车"

    def logistics_order_detail(self):
        # 物流单详情
        url = urljoin(self.env.realmName, "logistics-order/detail-sources")
        params = {
            "no": self.logistics_order_no
        }
        res = sendRequest(url, "get", headers=self.auser.headers,
                          params=params, msg="物流单详情")
        if res.status_code != 200:
            self.status = f"物流单装货详情获取失败：{res.text}"
            return
        self.return_details = [{
            "bitchNo": detail["batchNo"],
            "code": detail["goodsNo"],
            "name": detail["goodsName"],
            "spec": detail["goodsSpec"],
            "produceWeight": detail["weight"],
            "logisticsAreaCode": detail["loadingCode"],
            "logisticsAreaName": detail["loadingName"],
            "logisticsOperator": "李四-模拟",
            "logisticsOperatorTime": details["confirmeTime"],
            "number": 1,
            "tagCode": detail["barcode"],
            "unit": detail["unit"],
            "unitNo": detail["cargoTagNo"],
            "logisticsStore": detail["storeName"],
            "logisticsStoreCode": "1001V21000000002FASU"
        } for details in res.json() for detail in details["details"]]

    def transport_order_stowage(self):

        url = urljoin(self.env.realmName, "wms-system/loading-order-update")
        data = {
            "transportOrderNo": self.transport_no,
            "cargoDetails": [
                {
                    # 批次号  GPCH+物料编号+时间戳
                    "bitchNo": f'GPCH{details["goodsNo"]}{timeStamp()}',
                    # 物料名称
                    "name": f'{details["goodsName"]}',
                    # 物料编码
                    "code": f'{details["goodsNo"]}',
                    # 物料规格
                    "spec": f'{details["goodsSpec"]}',
                    # 单捆重量
                    "produceWeight": f'{details["unitWeight"]}',
                    # 固定
                    "number": 1,
                    # 标签号  GBQH+物料编号+时间戳
                    "tagCode": f'GBBQ{details["goodsNo"]}{timeStamp()}',
                    "unit": "捆",
                    # 不能重复 捆号
                    "unitNo": f'GBQH{details["goodsNo"]}{timeStamp()}',
                    # 装货仓库
                    "logisticsStore": f'{loadings["warehouseName"]}',
                    # 装货仓库编码
                    "logisticsStoreCode": f'{loadings["warehouseCode"]}',
                    # 装货区域编码
                    "logisticsAreaCode": f'{details["loadingCode"]}',
                    # 装货区域名称
                    "logisticsAreaName": f'{details["loadingName"]}',
                    # 装货操作人
                    "logisticsOperator": f"装车人编号{random.choice([1, 2, 3])}",
                    "logisticsOperatorTime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
                }for loadings in self.loadings for details in loadings["details"] for _ in range(details["count"])
            ]

        }
        # if stgeData:
        #     for cargoDetail in data["cargoDetails"]:
        #         stgeData["cargoDetails"].append(cargoDetail)
        # print("=========装货==============")
        # for loadings in self.loadings:
        #     print(f"库名: {loadings['warehouseName']}")
        #     for details in loadings["details"]:
        #         print(f"装物料: {details['goodsNo']} {details['count']}")
        # print("==========================")
        sendRequest(url, "post", js=data, headers=self.puser.headers, msg="装货")
        self.status = "装货成功"

    def transport_order_check_up(self):
        # 检验
        # url = urljoin(
        #     self.env.realmName, "transport-order-task/weighing-docs-status-sync")

        # res = sendRequest(
        #     url, "post", headers=self.puser.headers, msg="二次过磅前审核")
        # self.status = "已装货(已检查)"
        url = urljoin(self.env.realmName, "wms-system/loading-order-audit")
        data = {
            "transportOrderNo": self.transport_no,
            "auditPass": True,
            "operator": "李四-模拟",
            "operatorTime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            "outboundRemark": f"备注 {self.transport_no}"
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.auser.headers, msg="装货-审核")
        if res.status_code == 200:
            if res.json()["isSuccess"]:
                self.status = "装货-审核成功"
            else:
                self.status = f"装货-审核失败: {res.json()['message']}"
        else:
            self.status = f"装货-审核报错: {res.text}"

    def transport_order_second_loadmeter(self, loadings, callbacksure=0, callCode=0):
        # 二次过磅
        weightSum = 0
        weightSum += self.car_weight
        weightSum += sum([details["weight"]
                         for details in loadings["details"]])
        # if str(self.loadings).find("钢坯") >= 0:
        #     callbacksure = 1
        #     callCode = self.loadings[0]["errorHandleCode"]
        url = urljoin(self.env.realmName, "les-system/weight")
        data = {
            # 固定
            "cardType": 14,
            # 地磅次数
            "alreadyWeightCount": 2,
            # 总重量
            "weight": weightSum*1000,
            "weighbridgeName": self.weighbridge_name,
            # 1、皮重   2、毛重
            "weightType": 2,
            # 0 表示自动抬杠  1 表示手动抬杠（钢坯需要手动抬杠）
            "callbacksure": callbacksure,
            "callCode": callCode,
            # 卡号
            "cardNo": self.card_no,
            # 装车单号
            "cardOrderNo": self.transport_no,
            # 过磅单号
            "poundOrderNo": self.pound_order_no,
            # 操作人
            "operator": "张三模拟"
        }
        print(f"过磅重量： {weightSum}")
        # 过磅差异率=|生产重量（测试环境=理重） - （二次过磅差异值）| / 生产重量
        res = sendRequest(url, "post", js=data,
                          headers=self.puser.headers, msg="二次过磅")
        if res.status_code == 200:
            if str(res.json()["codeState"]) != "1":
                self.status = f"二次过磅失败: {res.json()}"
            else:
                self.status = "二磅已过待出厂"
        else:
            self.status = f"二磅失败: {res.text}"

    def transport_order_out_of_factory(self):
        # 出厂
        url = urljoin(
            self.env.realmName, "acs-system/finish-product-in-out-vehicle-log")
        data = {
            "inOrOutID": str(uuid.uuid1()),
            "inOrOut": "出",
            "plateNo": self.plate_number,
            "plateColor": "Y",
            "past": self.door,
            "pastChannel": "出口通道",
            "pastName": self.door,
            "pastChannelName": "出口通道2",
            "inOrOutDatetime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            "envPicUrl": "https://dummyimage.com/180x150",
            "carPicUrl": "https://dummyimage.com/180x150",
            "calculateNo": self.transport_no
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.puser.headers, msg="出厂")
        self.status = "已出厂"

    def transport_order_arrival(self):
        # 到货
        url = urljoin(self.env.realmName,
                      f"driver-client/transport-order-arrival")
        data = {
            "transportOrderNo": self.transport_no,
            "address": "江苏省苏州市张家港市",
            "position": {
                # "y": 118,
                # "x": 33
                "y": 120.555979,
                "x": 31.876739
            }
        }
        res = sendRequest(url, "post", data, self.auser.headers, msg="运单到货确认")

    def transport_order_signfor(self):
        # 签收
        url = urljoin(self.env.realmName,
                      f"driver-client/transport-order-signfor")
        data = {
            "transportOrderNo": self.transport_no,
            "signforPhoto": "http://tms2-sit.bxgt.com/file/api/file-management/files/www/new/3a19064cd9492f51c83d9a3c4dd6ec7f.jpg",
            "unloadPhoto": "http://tms2-sit.bxgt.com/file/api/file-management/files/www/new/3a19064ce0ae164c17ceb46dfc3f2ffb.jpg",
            "otherPhoto": "http://tms2-sit.bxgt.com/file/api/file-management/files/www/new/3a19064cf716e02f494bc174325293fc.jpg",
            "signPhoto": "",
            "address": "江苏省苏州市张家港市",
            "position": {
                "y": 120.555979,
                "x": 31.876739
            }
        }
        res = sendRequest(url, "post", data, self.auser.headers, msg="运单签收")

    def freeze_apply(self):
        # 冻结申请
        url = urljoin(self.env.realmName, "transport-order/freeze")
        data = {
            "transportOrderNo": self.transport_no,
            "reason": "车辆无立柱/挡板，不符合安全规定",
            "remark": "345654",
            "orderNo": self.transport_no
        }
        sendRequest(url, "post", js=data,
                    headers=self.puser.headers, msg="冻结申请")
        self.status = "冻结申请"

    def freeze_seach(self):
        # 冻结单查询
        url = urljoin(self.env.realmName, f"freeze-request-order/search")
        params = {
            "TransportOrderNo": self.transport_no,
            "MaxResultCount": 50,
            "SkipCount": 0,
            "BeginCreationTime": "",
            "EndCreationTime": "",
            "StatusArray": 0
        }
        res = sendRequest(url, "get", headers=self.puser.headers,
                          params=params, msg="冻结单查询")
        if res.status_code == 200 or res.status_code == 204:
            if len(res.json()["items"]) > 0:
                self.freeze_no = res.json()["items"][0]["requestNo"]

    def freeze_apply_audit(self):
        # 冻结审核通过
        self.freeze_seach()
        if not self.freeze_no:
            self.status = "未找到冻结单号"
            return
        url = urljoin(self.env.realmName, "freeze-request-order/audit")
        data = {
            "RequestNo": self.freeze_no,
            "isPunish": False,
            "status": 1,
            "punishAmount": None
        }
        res = sendRequest(url, "post", data,
                          headers=self.puser.headers, msg="冻结审核通过")
        self.status = "冻结审核通过"

    def freeze_affirm(self):
        # 冻结确认
        if not self.freeze_no:
            self.status = "未找到冻结单号"
            return
        url = urljoin(self.env.realmName,
                      "freeze-request-order/carrier-confirm")
        data = {
            "requestNo": self.freeze_no,
            "status": 1
        }
        res = sendRequest(url, "post", data,
                          headers=self.puser.headers, msg="冻结确认")
        self.status = "冻结确认"

    def freeze_stowage_cancel(self):
        # 冻结单装货取消
        url = urljoin(self.env.realmName, "wms-system/loading-order-audit")
        data = {
            "transportOrderNo": self.transport_no,
            "auditPass": False,
            "operator": "李四-模拟",
            "operatorTime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            "outboundRemark": f"备注 {self.transport_no}"
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.auser.headers, msg="装货取消")
        if res.status_code == 200:
            if res.json()["isSuccess"]:
                self.status = "装装货取消"
            else:
                self.status = f"装货取消失败: {res.json()['message']}"
        else:
            self.status = f"装货取消报错: {res.text}"

    def freeze_loadometer(self):
        # 冻结单过磅
        weightSum = 0
        weightSum += self.car_weight
        url = urljoin(self.env.realmName, "les-system/weight")
        data = {
            # 固定
            "cardType": 14,
            # 地磅次数
            "alreadyWeightCount": 2,
            # 总重量
            "weight": weightSum*1000,
            "weighbridgeName": self.weighbridge_name,
            # 1、皮重   2、毛重
            "weightType": 2,
            # 固定
            "callbacksure": 0,
            "callCode": 0,
            # 卡号
            "cardNo": self.card_no,
            # 装车单号
            "cardOrderNo": self.transport_no,
            # 过磅单号
            "poundOrderNo": self.pound_order_no,
            # 操作人
            "operator": "张三模拟"
        }
        print(f"过磅重量： {weightSum}")
        # 过磅差异率=|生产重量（测试环境=理重） - （二次过磅差异值）| / 生产重量
        res = sendRequest(url, "post", js=data,
                          headers=self.puser.headers, msg="二次过磅")
        if str(res.json()["codeState"]) != "1":
            print(f"二次过磅失败")
            return
        self.status = "二磅已过待出厂"

    def return_app_sign(self):
        # 司机签到
        url = urljoin(self.env.realmName,
                      f"driver-client/transport-order-signin")
        data = {
            "transportOrderNo": self.transport_no,
            "position": {
                "y": 119.285547,
                "x": 35.107886
            },
            "orderType": 2,
            "address": "江苏省连云港市赣榆区拓汪镇青岛大道"
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.auser.headers, msg="运单签到")
        if res.status_code == 200:
            if res.json()["status"] == "Succ":
                self.status = "司机签到成功"
            else:
                self.status = res.json()["exceptionMsg"]
        else:
            self.status = f"司机签到失败: {res.text}"

    def app_get_transport_order_detail(self):
        # 运单详情
        url = urljoin(self.env.realmName, "driver-client/transport-order")
        params = {
            "transportOrderNo": self.transport_no
        }
        res = sendRequest(url, "get", headers=self.auser.headers,
                          params=params, msg="运单详情")
        self.loadings = res.json()["loadings"]
        self.details = res.json()["details"]

    def return_info_factory(self):
        # 退回进厂
        self.app_get_transport_order_detail()
        warehouseName = self.loadings[0]["warehouseName"]
        store = self.store_dict[warehouseName]
        self.door = store["entry"]
        weighbridge_name = store["weighbridgeNames"]
        if len(weighbridge_name) < 1:
            self.weighbridge_name = ""
        else:
            self.weighbridge_name = weighbridge_name[0]
        self.transport_order_into_factory()
        self.status = "退回-已进厂"

    def return_first_loadometer(self):
        # 首次退回过磅
        self.app_get_transport_order_detail()
        allot_weight = sum([d["allotWeight"] for d in self.details])
        allot_weight += self.car_weight
        url = urljoin(self.env.realmName, "les-system/weight")
        data = {
            # 固定
            "cardType": 14,
            # 当前过磅次数
            "alreadyWeightCount": 1,
            # 重量
            "weight": allot_weight*1000,
            # ==============地磅名称=证仓库库别-关联地磅
            "weighbridgeName": self.weighbridge_name,
            "weightType": 2,
            "callbacksure": 0,
            "callCode": 0,
            # 卡号
            "cardNo": self.card_no,
            # 装车单号
            "cardOrderNo": self.transport_no,
            # 磅单号
            "poundOrderNo": self.pound_order_no,
            "operator": "张三模拟"
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.puser.headers, msg="首次过磅")
        if res.status_code == 200:

            self.status = f"{res.json()['message']}: 首磅已过"
        else:
            self.status = f"退回-首磅过磅失败: {res.text}"

    def return_loading(self):
        # 退回卸货
        self.logistics_order_detail()
        if self.return_details is None:
            self.status = "获取物流单详情失败"
            return self.status
        url = urljoin(self.env.realmName, "wms-system/loading-order-update")
        data = {
            "transportOrderNo": self.transport_no,
            "cargoDetails": [
                {
                    "bitchNo": detail["bitchNo"],
                    "code": detail["code"],
                    "name": detail["name"],
                    "spec": detail["spec"],
                    "produceWeight": f"{detail['produceWeight']}",
                    "logisticsAreaCode": detail["logisticsAreaCode"],
                    "logisticsAreaName": detail["logisticsAreaName"],
                    "logisticsOperator": "李四-模拟",
                    "logisticsOperatorTime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
                    "number": 1,
                    "tagCode": detail["tagCode"],
                    "unit": detail["unit"],
                    "unitNo": detail["unitNo"],
                    "logisticsStore": detail["logisticsStore"],
                    "logisticsStoreCode": detail["logisticsStoreCode"]
                } for detail in self.return_details
            ]
        }
        res = sendRequest(url, "post", headers=self.auser.headers, js=data)
        if res.status_code == 200:
            if res.json()["isSuccess"]:
                self.status = "退回-已装货"
            else:
                self.status = f"退回-装货失败: {res.json()['message']}"
        else:
            self.status = f"退回-装货报错: {res.text}"

    def return_order_audit(self):
        # 退回审核
        url = urljoin(self.env.realmName, "wms-system/loading-order-audit")
        data = {
            "transportOrderNo": self.transport_no,
            "auditPass": True,
            "operator": "李四-模拟",
            "operatorTime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            "outboundRemark": f"备注 {self.transport_no}"
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.auser.headers, msg="退回-审核")
        if res.status_code == 200:
            if res.json()["isSuccess"]:
                self.status = "退回-审核成功"
            else:
                self.status = f"退回-审核失败: {res.json()['message']}"
        else:
            self.status = f"退回-审核报错: {res.text}"

    def return_two_loadometer(self):
        # 退回二磅

        weight = sum([pound["weight"] for pound in self.pound_info]) - \
            sum([loading["actualWeight"] for loading in self.loadings])

        url = urljoin(self.env.realmName, "les-system/weight")
        data = {
            # 固定
            "cardType": 14,
            # 地磅次数
            "alreadyWeightCount": 2,
            # 总重量
            "weight": weight*1000,
            "weighbridgeName": self.weighbridge_name,
            # 1、皮重   2、毛重
            "weightType": 1,
            # 固定
            "callbacksure": 0,
            "callCode": 0,
            # 卡号
            "cardOrderNo": self.transport_no,
            # 过磅单号
            "poundOrderNo": self.pound_order_no,
            # 操作人
            "operator": "张三模拟"
        }
        # 过磅差异率=|生产重量（测试环境=理重） - （二次过磅差异值）| / 生产重量
        res = sendRequest(url, "post", js=data,
                          headers=self.auser.headers, msg="二次过磅")
        if res.status_code == 200:
            if str(res.json()["message"]) == "请通过！":
                self.status = "退回-二磅已过"
            else:
                self.status = f"退回-二磅过磅失败: {res.json()['message']}"
        else:
            self.status = f"退回-二磅过磅报错: {res.text}"

    def return_out_of_factory_audit(self):
        # 退回出厂审核
        url = urljoin(self.env.realmName,
                      "transport-order-task/tms_Outbound-order-audit")
        data = {
            "no": self.transport_no
        }
        res = sendRequest(url, "post", js=data,
                          headers=self.auser.headers, msg="退回-出厂审核")
        if res.status_code == 204:
            self.status = "退回-出厂审核成功"
        else:
            self.status = f"退回-出厂审核报错: {res.text}"
